use crate::dto::{
    dict::{
        AddDictType, AddSysDictDataVo, DictDataDetail, DictTypeDataPagePayload,
        DictTypePagePayload, EditSysDictData,
    },
    res_json_custom, res_json_ok, Page, Res, ResObj,
};
use crate::entity::{
    sys_dict_data::SysDictData,
    sys_dict_type::{ModifySysDictType, SysDictType},
};
use crate::service::dict_service;
use hypers::prelude::*;

pub struct Dict;

#[openapi(prefix = "/system", name = "/dict", tag = "字典")]
impl Dict {
    /// 字典类型列表
    #[get(
        "/type/list",
        parameter(DictTypePagePayload),
        response(
            (status = 200,body=ResObj<Page<SysDictType>>,description ="字典类型列表")
        ),
    )]
    async fn get_dict_list(req: &mut Request) -> Res<Page<SysDictType>> {
        let page_num = req.query::<u64>("pageNum").map_or(1, |v| v);
        let page_size = req.query::<u64>("pageSize").map_or(10, |v| v);
        let dict_name = req.query::<&str>("dictName").map_or("", |v| v);
        let dict_type = req.query::<&str>("dictType").map_or("", |v| v);
        let status = req.query::<&str>("status").map_or("", |v| v);
        let begin_time = req.query::<&str>("params[beginTime]").map_or("", |v| v);
        let end_time = req.query::<&str>("params[endTime]").map_or("", |v| v);
        match dict_service::get_dict_by_page(
            page_num, page_size, dict_name, dict_type, status, begin_time, end_time,
        )
        .await
        {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 字典类型数据列表
    #[get(
        "/data/list",
        parameter(
            DictTypeDataPagePayload
        ),
        response(
            (status = 200,body=ResObj<Page<SysDictData>>,description ="字典类型数据列表")
        ),
    )]
    async fn get_dict_data_list(payload: DictTypeDataPagePayload) -> Res<Page<SysDictData>> {
        match dict_service::get_dict_data_by_page(
            payload.page_num,
            payload.page_size,
            payload.dict_type.clone(),
            payload.status.clone(),
            payload.dict_label.clone(),
        )
        .await
        {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 创建字典数据
    #[post(
        "/data",
        response(
            (status = 200,body=ResObj<()>,description ="创建字典数据")
        )
    )]
    async fn post_add_dict_data(payload: Json<AddSysDictDataVo>, depot: &mut Request) -> Res<()> {
        let user_id = depot.get::<i32>("userId").unwrap();
        match dict_service::add_dict_data(user_id, payload.0).await {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "删除失败".to_string()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 修改字典数据
    #[put(
        "/data",
        response(
            (status = 200,body=ResObj<()>,description ="修改字典数据")
        )
    )]
    async fn put_edit_dict_data(payload: Json<EditSysDictData>) -> Res<()> {
        match dict_service::edit_dict_data(payload.0).await {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "删除失败".to_owned()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 删除字典类型数据
    #[delete(
        "/data/:id",
        response(
            (status = 200,body=ResObj<()>,description ="删除字典类型数据")
        )
    )]
    async fn del_dict_type_data(id: Path<String>) -> Res<()> {
        let code = id.0.split(",").collect::<Vec<&str>>();
        if code.len() == 0 {
            return Err(res_json_custom(400, "缺少参数".to_string()));
        }
        match dict_service::del_dict_data_type(code).await {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "删除失败".to_owned()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 字典类型数据详情
    #[get(
        "/data/:id",
        parameter(
            DictDataDetail
        ),
        response(
            (status = 200,body=ResObj<Option<SysDictData>>,description ="字典类型数据详情")
        )
    )]
    async fn get_dict_type_data_by_id(code: DictDataDetail) -> Res<Option<SysDictData>> {
        match dict_service::select_dict_data_by_id(code.id).await {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 根据类型获取字典数据列表
    #[get(
        "/data/type/:type_id",
        response(
            (status = 200,body=ResObj<Vec<SysDictData>>,description ="根据类型获取字典数据列表")
        ),
    )]
    async fn get_dict_list_by_type(type_id: Path<&str>) -> Res<Vec<SysDictData>> {
        match dict_service::get_dict_data_by_type(type_id.0).await {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 获取所有字典类型
    #[get(
        "/type/optionselect",
        response(
            (status = 200,body=ResObj<Vec<SysDictType>>,description ="获取所有字典类型")
        ),
    )]
    async fn get_all_dict_type() -> Res<Vec<SysDictType>> {
        match dict_service::get_all_dict_type().await {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 根据id获取字典类型数据
    #[get(
        "/type/:id",
        response(
            (status = 200,body=ResObj<Option<SysDictType>>,description ="根据id获取字典类型数据")
        ),
    )]
    async fn get_dict_by_id(id: Path<i64>) -> Res<Option<SysDictType>> {
        match dict_service::get_dict_by_id(id.0).await {
            Ok(v) => Ok(res_json_ok(Some(v))),
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 删除字典类型
    #[get(
        "/type/:id",
        response(
            (status = 200,body=ResObj<()>,description ="删除字典类型")
        )
    )]
    async fn del_dict_type(id: Path<String>) -> Res<()> {
        let code = id.split(",").collect::<Vec<&str>>();
        if code.len() == 0 {
            return Err(res_json_custom(400, "缺少参数".to_owned()));
        }
        match dict_service::del_dict_type(code).await {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "删除失败".to_owned()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 创建字典类型
    #[post(
        "/type",
        response(
            (status = 200,body=ResObj<()>,description ="创建字典类型")
        )
    )]
    async fn add_dict_type(dict: Json<AddDictType>, depot: &mut Request) -> Res<()> {
        let user_id = depot.get::<i32>("userId").unwrap();
        match dict_service::add_dict_type(
            user_id,
            dict.dict_name.clone(),
            dict.dict_type.clone(),
            dict.status.clone(),
            dict.remark.clone(),
        )
        .await
        {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "添加失败".to_owned()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }

    /// 修改字典类型
    #[put(
        "/type",
        response(
            (status = 200,body=ResObj<()>,description ="修改字典类型")
        )
    )]
    async fn edit_dict_type(dict: Json<ModifySysDictType>, depot: &mut Request) -> Res<()> {
        let user_id = depot.get::<i32>("userId").unwrap();
        match dict_service::edit_dict_type(user_id, dict).await {
            Ok(v) => {
                if v {
                    Ok(res_json_ok(Some(())))
                } else {
                    Err(res_json_custom(400, "修改失败".to_owned()))
                }
            }
            Err(err) => Err(res_json_custom(400, err.to_string())),
        }
    }
}
